package uabc.arduino.monitores;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;

import javax.swing.JOptionPane;

public class MonitorSerial extends Monitor implements SerialPortEventListener {
	private SerialPort serialPort;
	private BufferedReader input;
	private OutputStream output;
	private String port;
	private static final int TIME_OUT = 2000;
	private static final int DATA_RATE = 9600;
	private boolean running;

	public MonitorSerial(String port) {
		super();
		this.running = true;
		this.port = port;
		initialize();
	}

	public void initialize() {
		CommPortIdentifier portId = null;
		Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

		while (portEnum.hasMoreElements()) {
			CommPortIdentifier currPortId = (CommPortIdentifier) portEnum
					.nextElement();
			System.out.println(currPortId.getName());
			portId = currPortId;
			if (currPortId.getName().equals(port)) {
				portId = currPortId;
				break;
			}
		}
		if (portId == null) {
			JOptionPane.showMessageDialog(null, "No se encontro el puerto",
					"Puerto No Encontrado", JOptionPane.WARNING_MESSAGE);
			return;
		}

		try {
			serialPort = (SerialPort) portId.open(this.getClass().getName(),
					TIME_OUT);

			serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

			input = new BufferedReader(new InputStreamReader(
					serialPort.getInputStream()));
			output = serialPort.getOutputStream();

			serialPort.addEventListener(this);
			serialPort.notifyOnDataAvailable(true);
		} catch (Exception e) {
			System.err.println(e.toString());
		}
	}

	public synchronized void serialEvent(SerialPortEvent oEvent) {
		if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			try {
				String cadena = input.readLine();
				System.out.println(cadena);
				setChanged();
				notifyObservers(cadena);
			} catch (IOException e) {
				// e.printStackTrace();
			}
		}
	}

	public synchronized void close() {
		if (serialPort != null) {
			serialPort.removeEventListener();
			serialPort.close();
		}
	}

	public void run() {
		while (running) {
		}
		System.out.println("Termina");
	}

	@Override
	public void ejecutarComando(String comando) {
		comando += "\n";
		try {
			if (comando.length() <= 50)
				this.output.write(comando.getBytes());
			else {
				int longitud = comando.length();
				int iteraciones = longitud / 50;
				for (int x = 0; x <= iteraciones; x++) {
					int index = x * 50;
					int fin = index + 50;
					if (fin > longitud)
						fin = longitud;
					String subcadena = comando.substring(index, fin);
					this.output.write(subcadena.getBytes());
					delay(500);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void terminate() {
		running = false;
		close();
	}

	public void delay(long miliSeconds) {
		try {
			Thread.sleep(miliSeconds);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean testConnection() {
		// TODO Auto-generated method stub
		return false;
	}

}
